home *** CD-ROM | disk | FTP | other *** search
/ Gigantic Games 2 / Gigantic Games 2.iso / pc / _z_ / zorkmachine / mem.c < prev    next >
C/C++ Source or Header  |  1994-12-23  |  5KB  |  307 lines

  1. /*
  2. *    @(#)mem.c    2.24
  3. */
  4.  
  5. # include "zmachine.h"
  6.  
  7. #ifdef AMIGA
  8.  
  9. #undef NULL
  10. #define NULL 0L
  11.  
  12. #endif
  13.  
  14. # define LOCK    0xffffffffL
  15.  
  16. UBYTE *main_p;        /* main memory pointer                */
  17. int main_l;        /* main memory len in pages            */
  18. struct header *main_h;    /* header pointer                */
  19.  
  20. struct virt_page *pc_page;    /* page of current pc            */
  21. struct virt_page main_page;    /* page control for main memory        */
  22. struct virt_page *c_page;     /* current active page            */
  23. struct virt_page *virt_p;    /* the virtual memory array        */
  24. struct address    pc;        /* program counter            */
  25.  
  26. unsigned long lruc =  0;    /* LRU counter                */
  27.  
  28. /************************************************************************/
  29.  
  30. /* find free page */
  31.  
  32. struct virt_page *find_page()
  33. {
  34.     register struct virt_page *u, *v;
  35.     register long t;
  36.  
  37.     for(v = virt_p, t = LOCK; v->page != -1; v++)
  38.         if (v->lru < t)
  39.         {
  40.             t = v->lru;
  41.             u = v;
  42.         }
  43.  
  44.     return(u);
  45. }
  46.  
  47.  
  48. /* load a page */
  49.  
  50. UBYTE *load_page(page)
  51. register WORD page;
  52. {
  53.     register struct virt_page *v;
  54.  
  55.     if (page != c_page->page)
  56.     {
  57.         lruc++;
  58.         for (v = virt_p; v->page != -1; v++)
  59.         {
  60.             if (v->page == page)
  61.             {
  62.                 if (pc_page->page != page)
  63.                     v->lru = lruc;
  64.  
  65.                 c_page = v;
  66.                 return(c_page->paddr);
  67.             }
  68.         }
  69.         c_page = find_page();
  70.         c_page->page = page;
  71.         c_page->lru = lruc;
  72.         read_story(c_page->page, 1, c_page->paddr);
  73.     }
  74.     return(c_page->paddr);
  75. }
  76.  
  77.  
  78. /* load page for current pc */
  79.  
  80. void load_code()
  81. {
  82.     pc.segment += pc.offset >> 9;    /* pc.offset may be negative    */
  83.     pc.offset &= 0x1ff;
  84.     if (pc.segment != pc_page->page)
  85.     {
  86.         pc_page->lru = lruc;
  87.  
  88.         if (pc.segment >= main_l)
  89.         {
  90.             load_page(pc.segment);
  91.             pc_page = c_page;
  92.             pc_page->lru = LOCK;
  93.         }
  94.         else
  95.         {
  96.             main_page.page = pc.segment;
  97.             main_page.paddr = main_p+ptob(pc.segment);
  98.             pc_page = &main_page;
  99.         }
  100.     }
  101. }
  102.  
  103.  
  104. /* page to byte address */
  105.  
  106. long ptob(page)
  107. UWORD page;
  108. {
  109.     return(((long)page << (long)9) & 0x1ffffL);
  110. }
  111.  
  112.  
  113. /* byte to page address */
  114.  
  115. UWORD btop(byte)
  116. long byte;
  117. {
  118.     return((byte & 0x1ff ? (byte >> 9)+1:(byte >> 9)) & 0xff);
  119. }
  120.  
  121.  
  122. /* get word */
  123.  
  124. UWORD word_get(p)
  125. UBYTE *p;
  126. {
  127.     register UWORD i;
  128.     i = *p++ << 8;
  129.     return(i | *p);
  130. }
  131.  
  132.  
  133. /* put word */
  134.  
  135. void word_put(p, d)
  136. UBYTE *p; register UWORD d;
  137. {
  138.     p[1] = d & 0xff;
  139.     p[0] = d >> 8;
  140. }
  141.  
  142.  
  143. /* fetch byte data */
  144.  
  145. UBYTE fetchb_data(a)
  146. register struct address *a;
  147. {
  148.     UBYTE *load_page();
  149.     register UBYTE r;
  150.  
  151.     if (a->segment < main_l)
  152.         r = main_p[ptob(a->segment) | a->offset];
  153.     else
  154.         r = load_page(a->segment)[a->offset];
  155.  
  156.     if (++(a->offset) == 0x200)
  157.     {
  158.         a->offset = 0;
  159.         (a->segment)++;
  160.     }
  161.     return(r);
  162. }
  163.  
  164.  
  165. /* fetch word data */
  166.  
  167. UWORD fetchw_data(a)
  168. struct address *a;
  169. {
  170.     register UWORD r;
  171.     r = fetchb_data(a);
  172.     return((r << 8) | fetchb_data(a));
  173. }
  174.  
  175.  
  176. /* fetch next byte from pc */
  177.  
  178. UBYTE fetchb_op()
  179. {
  180.     register UBYTE r;
  181.  
  182.     r = pc_page->paddr[pc.offset];
  183.     if (++pc.offset >= 0x200)
  184.         load_code();
  185.  
  186.     return(r);
  187. }
  188.  
  189.  
  190. /* fetch next word from pc */
  191.  
  192. UWORD fetchw_op()
  193. {
  194.     register UWORD r;
  195.  
  196.     r = fetchb_op() << 8;
  197.     return(r | fetchb_op());
  198. }
  199.  
  200.  
  201. /* byte address to virtual address */
  202.  
  203. void baddr_to_vaddr(vaddress, baddress)
  204. register struct address *vaddress; register UWORD baddress;
  205. {
  206.     vaddress->segment = (baddress >> 9) & 0xff;
  207.     vaddress->offset = baddress & 0x1ff;
  208. }
  209.  
  210.  
  211. /* word address to virtual address */
  212.  
  213. void waddr_to_vaddr(vaddress, waddress)
  214. struct address *vaddress; register UWORD waddress;
  215. {
  216.     vaddress->segment = (waddress >> 8) & 0xff;
  217.     vaddress->offset = (waddress & 0xff) * 2;
  218. }
  219.  
  220.  
  221. /* initialize mmu */
  222.  
  223. #if defined(minix)
  224. extern int brk();
  225. extern char *sbrk();
  226. static char *oldbrk = NULL;
  227. static char *lmalloc(s)
  228. long s;
  229. {
  230.     char *m;
  231.     if (!oldbrk)
  232.         oldbrk = sbrk(0);
  233.  
  234.     m = sbrk(0);
  235.     if (brk(m + s + 0x2000) != 0)
  236.     {
  237.         brk(m);
  238.         return(NULL);
  239.     }
  240.     else
  241.     {
  242.         brk(m + s);
  243.         return(m);
  244.     }
  245. }
  246.  
  247. static free(p)
  248. char *p;
  249. {
  250.     brk(oldbrk);
  251. }
  252. #endif
  253.  
  254. void mmu_init(h)
  255. struct header *h;
  256. {
  257.     long virt_l;
  258.     int i;
  259.  
  260.     if (main_p = (UBYTE *)lmalloc(btop((long)word_get(h->len) * 2L) * 512L))
  261.     {
  262.         main_l = btop((long)word_get(h->len) * 2L);
  263.         virt_l = 2;
  264.         if (!(virt_p = (struct virt_page *)lmalloc((0x200L +
  265.                     sizeof(struct virt_page)) * 2 +
  266.                     sizeof(struct virt_page))))
  267.         {
  268.             free(main_p);
  269.             goto low_mem;
  270.         }
  271.     }
  272.     else
  273.     {
  274. low_mem:
  275.         if ((main_p = (UBYTE *)
  276.             lmalloc((long)btop((long)word_get(h->minmem)) * 512L))
  277.                == NULL)
  278.             no_mem_error();
  279.  
  280.         main_l = btop((long)word_get(h->minmem));
  281.  
  282.         for (virt_l = btop((long)word_get(h->len) * 2L -
  283.             (long)word_get(h->minmem));
  284.                 virt_l >= 2 && virt_p == NULL; virt_l--)
  285.             virt_p = (struct virt_page *)lmalloc((long)
  286.                 (virt_l * (0x200L +
  287.                 sizeof(struct virt_page)) +
  288.                 sizeof(struct virt_page)));
  289.  
  290.         if (virt_l < 2)
  291.             no_mem_error();
  292.     }
  293.  
  294.     for (i = 0; i < virt_l; i++)
  295.     {
  296.         virt_p[i].page = -2;
  297.         virt_p[i].lru = 0L;
  298.         virt_p[i].paddr = (UBYTE *)virt_p +
  299.                 (long)(sizeof(struct virt_page) *
  300.                 (virt_l + 1L) + 0x200L * (long)i);
  301.     }
  302.     virt_p[i].page = -1;
  303.  
  304.     pc_page = c_page = virt_p;
  305.     main_h = (struct header *)main_p;
  306. }
  307.